package com.alibaba.algo.components.yapi.service.impl;

import java.lang.reflect.Method;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.algo.components.yapi.YapiDataCacheManger;
import com.alibaba.algo.components.yapi.annotations.Api;
import com.alibaba.algo.components.yapi.annotations.ApiOperation;
import com.alibaba.algo.components.yapi.entity.CatMenu;
import com.alibaba.algo.components.yapi.entity.InterfaceInfo;
import com.alibaba.algo.components.yapi.enums.ContentTypEnum;
import com.alibaba.algo.components.yapi.handler.RequestHandler;
import com.alibaba.algo.components.yapi.handler.ResponseHandler;
import com.alibaba.algo.components.yapi.service.YapiOpenService;
import com.alibaba.algo.components.yapi.service.YapiService;
import com.alibaba.algo.components.yapi.util.ClazzUtils;
import com.alibaba.algo.components.yapi.vo.InterfaceRequestVO;
import com.alibaba.algo.components.yapi.vo.RequestHandlerResponseVO;
import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class YapiServiceImpl implements YapiService {
	@Autowired
	private ResponseHandler responseHandler;
	@Autowired
	private Map<String, RequestHandler> requestHandlerMap;
	@Autowired
	private YapiOpenService yapiOpenService;

	@Override
	public void registerYapi(Integer catId, Class<?> controllerClass, Method[] methods) {
		// 获取接口URI
		String interfaceUri = "";
		RequestMapping requestMapping = AnnotationUtils.findAnnotation(controllerClass, RequestMapping.class);
		if (requestMapping != null && requestMapping.value() != null && requestMapping.value().length > 0) {
			interfaceUri = requestMapping.value()[0];
		}
		for (Method method : methods) {
			ApiOperation apiOperation = AnnotationUtils.findAnnotation(method, ApiOperation.class);
			if (apiOperation == null) {
				continue;
			}
			log.info("start handle method:{}", method.getName());
			// 判断接口状态
			InterfaceInfo interfaceInfo = YapiDataCacheManger
					.getInterfaceInfo(interfaceUri + ClazzUtils.getMethodUri(method), catId);
			if (interfaceInfo != null && interfaceInfo.getStatus().equals("done")) {
				log.info("method:{},该接口 {}，状态是已完成，过滤覆盖修改。。。", method.getName(), apiOperation.name());
				continue;
			}
			// 返回结果
			String resBody = responseHandler.handler(apiOperation.response(), apiOperation.isPaged(),
					apiOperation.isList());
			log.info("method:{} 返回参数：resBody:{}", method.getName(), resBody);

			// contentType 默认为JSON
			ContentTypEnum contentTypEnum = apiOperation.contentType();
			if (contentTypEnum == null) {
				contentTypEnum = ContentTypEnum.JSON;
			}
			RequestHandler requestHandler = requestHandlerMap.get(contentTypEnum.getHandler());
			if (requestHandler == null) {
				log.error("method:{} requestHandler is empty", method.getName());
				continue;
			}
			// request 参数获取
			RequestHandlerResponseVO requestHandlerResponseVO = requestHandler.handler(method);
			if (requestHandlerResponseVO == null) {
				log.error("method:{} 获取请求参数失败，请检查contentType与接口参数是否匹配", method.getName());
				continue;
			}
			log.info("请求参数：requestHandlerResponseVO:{}", JSON.toJSONString(requestHandlerResponseVO));
			requestHandlerResponseVO.setMethodUri(interfaceUri + requestHandlerResponseVO.getMethodUri());

			// yapi参数封装
			InterfaceRequestVO interfaceRequestVO = new InterfaceRequestVO();
			interfaceRequestVO.setResBodyType("json");
			interfaceRequestVO.setResBody(resBody);
			interfaceRequestVO.setMethod(requestHandlerResponseVO.getMethodType());
			interfaceRequestVO.setCatid(catId);
			interfaceRequestVO.setReqBodyType(requestHandlerResponseVO.getReqBodyType());
			interfaceRequestVO.setReqBodyOther(requestHandlerResponseVO.getReqBody());
			interfaceRequestVO.setReqBodyForm(requestHandlerResponseVO.getReqBodyForm());
			interfaceRequestVO.setReqHeaders(requestHandlerResponseVO.getReqHeaders());
			interfaceRequestVO.setReqQuery(requestHandlerResponseVO.getReqQuery());
			interfaceRequestVO.setTitle(apiOperation.name());
			interfaceRequestVO.setPath(requestHandlerResponseVO.getMethodUri());
			interfaceRequestVO.setSwitchNotice(true);
			if (requestHandlerResponseVO.getMethodType().equals("POST")) {
				interfaceRequestVO.setReqBodyIsJsonSchema(true);
			}
			interfaceRequestVO.setResBodyIsJsonSchema(true);
			boolean registerResult = yapiOpenService.save(interfaceRequestVO);
			log.info("method:{} register result:{}", apiOperation.name(), registerResult);
		}
	}

	@Override
	public Integer getCatId(Api apiAnnotation) {
		Integer catId = null;
		String catName = apiAnnotation.catName();
		if(StringUtils.isEmpty(catName)) {
			return catId;
		}
		CatMenu catMenu = YapiDataCacheManger.getCatMenu(catName);
		if (catMenu == null) {
			catId = yapiOpenService.addCat(apiAnnotation.desc(), catName, YapiDataCacheManger.getProject().getId());
		} else {
			catId = catMenu.getId();
		}
		return catId;
	}

}
